package com.study.core.error;

import com.study.core.resp.Resp;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.springframework.util.unit.DataSize;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

/**
 * @Description 全局异常处理器
 * @Author dangxianyue
 * @Date 2024/5/31 10:00
 */
@Slf4j
@RestControllerAdvice
public class GlobalErrorHandler {

    /**
     * 业务异常
     */
    @ExceptionHandler(BizException.class)
    public Resp handleBizException(BizException ex) {
        return Resp.fail(ex);
    }

    /**
     * 文件大小超限异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = MaxUploadSizeExceededException.class)
    public Resp handleMaxUploadSizeExceededExceptionException(MaxUploadSizeExceededException ex) {
        String msg;
        long permittedSize;
        if (ex.getCause().getCause() instanceof FileSizeLimitExceededException) {
            permittedSize = ((FileSizeLimitExceededException) ex.getCause().getCause()).getPermittedSize();
            msg = String.format("上传文件过大[单文件大小不得超过 %s Mb]", DataSize.ofBytes(permittedSize).toMegabytes());
        } else if (ex.getCause().getCause() instanceof SizeLimitExceededException) {
            permittedSize = ((SizeLimitExceededException) ex.getCause().getCause()).getPermittedSize();
            msg = String.format("上传文件过大[总上传文件大小不得超过 %s Mb]", DataSize.ofBytes(permittedSize).toMegabytes());
        } else {
            msg = "上传文件失败";
        }

        return Resp.fail(msg);

    }


    /**
     * 入参校验异常：application/json形式
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Resp handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        StringBuilder sb = new StringBuilder();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            if (sb.length() == 0) {
                sb.append(error.getDefaultMessage());
            } else {
                sb.append(", ").append(error.getDefaultMessage());
            }
        }
        return Resp.fail(sb.toString());
    }

    /**
     * 入参校验异常：x-www-form-urlencoded 请求方式
     */
    @ExceptionHandler(value = BindException.class)
    public Resp handleBindException(BindException ex) {
        StringBuilder sb = new StringBuilder();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            if (sb.length() == 0) {
                sb.append(error.getDefaultMessage());
            } else {
                sb.append(", ").append(error.getDefaultMessage());
            }
        }
        return Resp.fail(sb.toString());
    }

    /**
     * 其他错误
     */
    @ExceptionHandler({Exception.class})
    public Resp handleException(Exception ex) {
        log.error("服务器异常：", ex);
        return Resp.fail("服务器出错啦，请联系系统管理员~");
    }
}
